using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Matrix.Notification.Channels;
using Matrix.Notification.Options;

namespace Matrix.Notification.Notifications
{
    /// <summary>
    /// 通知发送服务实现（真实发送版本）
    /// </summary>
    public class NotificationSendingService : ITransientDependency
    {
        private readonly ILogger<NotificationSendingService> _logger;
        private readonly IEnumerable<INotificationChannel> _channels;
        private readonly NotificationOptions _options;

        public NotificationSendingService(
            ILogger<NotificationSendingService> logger,
            IEnumerable<INotificationChannel> channels,
            IOptions<NotificationOptions> options)
        {
            _logger = logger;
            _channels = channels ?? throw new ArgumentNullException(nameof(channels));
            _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
        }

        public async Task<bool> SendAsync(object notification, CancellationToken cancellationToken = default)
        {
            if (notification == null)
            {
                throw new ArgumentNullException(nameof(notification));
            }

            try
            {
                _logger.LogInformation("开始发送通知: {NotificationType}", notification.GetType().Name);

                // 确定使用哪个通道发送通知
                var channel = await DetermineChannelAsync(notification, cancellationToken);
                if (channel == null)
                {
                    _logger.LogWarning("未找到合适的通知通道: {NotificationType}", notification.GetType().Name);
                    return false;
                }

                _logger.LogInformation("使用 {ChannelType} 通道发送通知", channel.ChannelType);

                // 检查通道是否可用
                if (!await channel.IsAvailableAsync(cancellationToken))
                {
                    _logger.LogWarning("通知通道 {ChannelType} 不可用", channel.ChannelType);
                    return false;
                }

                // 发送通知
                var result = await channel.SendAsync(notification, cancellationToken);
                if (result.IsSuccess)
                {
                    _logger.LogInformation("通知发送成功: {ChannelType} - MessageId: {MessageId}",
                        channel.ChannelType, result.MessageId);
                    return true;
                }
                else
                {
                    _logger.LogError("通知发送失败: {ChannelType} - Error: {Error}",
                        channel.ChannelType, result.ErrorMessage);
                    return false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送通知时发生异常: {NotificationType}", notification.GetType().Name);
                return false;
            }
        }

        public async Task<int> SendBatchAsync(IReadOnlyCollection<object> notifications, CancellationToken cancellationToken = default)
        {
            if (notifications == null)
            {
                throw new ArgumentNullException(nameof(notifications));
            }

            if (notifications.Count == 0)
            {
                return 0;
            }

            try
            {
                _logger.LogInformation("开始批量发送通知: {Count} 条", notifications.Count);

                // 按通知类型分组
                var groupedNotifications = notifications.GroupBy(n => n.GetType()).ToList();
                var totalSuccessCount = 0;

                foreach (var group in groupedNotifications)
                {
                    _logger.LogInformation("处理 {NotificationType} 类型通知: {Count} 条", group.Key.Name, group.Count());

                    // 确定该类型通知使用的通道
                    var sampleNotification = group.First();
                    var channel = await DetermineChannelAsync(sampleNotification, cancellationToken);
                    if (channel == null)
                    {
                        _logger.LogWarning("未找到合适的通知通道: {NotificationType}", group.Key.Name);
                        continue;
                    }

                    // 检查通道是否可用
                    if (!await channel.IsAvailableAsync(cancellationToken))
                    {
                        _logger.LogWarning("通知通道 {ChannelType} 不可用", channel.ChannelType);
                        continue;
                    }

                    // 批量发送
                    var batchResult = await channel.SendBatchAsync(group.ToArray(), cancellationToken);
                    totalSuccessCount += batchResult.SuccessCount;

                    _logger.LogInformation("批量发送完成: {ChannelType} - 成功: {Success} 失败: {Failure}",
                        channel.ChannelType, batchResult.SuccessCount, batchResult.FailureCount);
                }

                _logger.LogInformation("批量发送完成: 总成功 {Success} 条，总计 {Total} 条", totalSuccessCount, notifications.Count);
                return totalSuccessCount;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量发送通知时发生异常");
                return 0;
            }
        }

        private async Task<INotificationChannel?> DetermineChannelAsync(object notification, CancellationToken cancellationToken)
        {
            // 根据通知类型确定使用的通道
            var notificationType = notification.GetType();

            return notificationType.Name switch
            {
                nameof(EmailNotification) => _channels.FirstOrDefault(c => c.ChannelType == "Email"),
                nameof(SmsNotification) => _channels.FirstOrDefault(c => c.ChannelType == "Sms"),
                nameof(PushNotification) => _channels.FirstOrDefault(c => c.ChannelType == "Push"),
                nameof(WebhookNotification) => _channels.FirstOrDefault(c => c.ChannelType == "Webhook"),
                _ => _channels.FirstOrDefault(c => c.ChannelType == "Email") // 默认使用邮件通道
            };
        }
    }
}